package fun._6742.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import fun._6742.enums.AuthorizationTypeEnums;
import fun._6742.exception.CustomException;
import fun._6742.mapper.UserMapper;
import fun._6742.model.dataobject.UserDO;
import fun._6742.model.valueobject.LoginUser;
import fun._6742.request.AdminLoginRequest;
import fun._6742.request.AdminRegisterRequest;
import fun._6742.service.AdminService;
import fun._6742.service.VerifyService;
import fun._6742.utils.CommonUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

import static fun._6742.utils.JwtParameter.*;

@Slf4j
@Service
public class AdminServiceImpl implements AdminService {

    @Resource
    UserMapper userMapper;

    @Resource
    VerifyService verifyService;

    @Override
    public String adminLogin(AdminLoginRequest adminLoginRequest, HttpServletRequest httpRequest) {
        List<UserDO> userDOList = userMapper.selectList(new QueryWrapper<UserDO>().eq("phone", adminLoginRequest.getPhone()));
        if (userDOList == null || userDOList.size() != 1) {
            throw new CustomException(HttpStatus.NOT_FOUND, "The phone number is not registered");
        }
        UserDO user = userDOList.get(0);
        checkUserType(user);
        checkPassword(adminLoginRequest, user);

        LoginUser loginUser = new LoginUser();
        BeanUtil.copyProperties(user, loginUser);

//      颁发token， 参考：https://www.hutool.cn/docs/#/jwt/JWT%E5%B7%A5%E5%85%B7-JWTUtil
        Map<String, Object> map = BeanUtil.beanToMap(loginUser);
        map.put("ip", CommonUtils.getIpAddr(httpRequest));
        map.put("expire_time", System.currentTimeMillis() + EXPIRE_TIME);
//        hutool默认将jwt.header置为null（不严谨的理解），默认将上述map的item放入Payload。
        String token = JWTUtil.createToken(map, KEY.getBytes());

        return token;
    }

    @Override
    public void adminRegister(String captchaKey, AdminRegisterRequest adminRegisterRequest) {
        //        仅通过图形验证码注册
        if (ObjectUtil.hasNull()) {
            throw new CustomException(HttpStatus.NOT_FOUND, "The registration information cannot contain empty item");
        }
        verifyService.verifyCode(captchaKey, adminRegisterRequest.getCode());
        checkUnique();

//        密码加密：结合hutool，使用sm3国密算法 摘要 加密  TODO 引入密码盐
        adminRegisterRequest.setPwd(DigestUtil.digester(ALGORITHM).digestHex(adminRegisterRequest.getPwd()));

        UserDO userDO = new UserDO(adminRegisterRequest);
        int res = userMapper.insert(userDO);
//        TODO 插入对象的长度校验，未来可以结合ResponseBody进行错误处理的改造
        log.info("res:{},registration success:{}", res, userDO);
    }




    private void checkUnique() {
//        TODO 手机号邮箱唯一性验证
        boolean phoneIsUnique = true;
        boolean mailIsUnique = true;
        if (!phoneIsUnique) {
            throw new CustomException(HttpStatus.NOT_FOUND,
                    "Email address already exists");
        }
        if (!mailIsUnique) {
            throw new CustomException(HttpStatus.NOT_FOUND,
                    "Phone number already exists");
        }
    }

    public void checkPassword(AdminLoginRequest adminLoginRequest, UserDO userDO) {
//        登陆密码sm3摘要加密 TODO 引入密码盐
        String pwdOfReqAfterMd5 = DigestUtil.digester(ALGORITHM).digestHex(adminLoginRequest.getPwd());
//        String pwdOfReqAfterMd5 = adminLoginRequest.getPwd();
        String pwdInDb = userDO.getPwd();
        if (!StrUtil.equals(pwdInDb,pwdOfReqAfterMd5)) {
            throw new CustomException(HttpStatus.NOT_FOUND, "incorrect password");
        }
    }

    private void checkUserType(UserDO user) {
        if (user.getUserType()!= AuthorizationTypeEnums.SHOPKEEPER.getCode()){
            throw new CustomException(HttpStatus.NOT_FOUND,"unacceptable user type, please change another account to log in");
        }
    }
}
